﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SimpleData.Infrastructure.Serialization;
using SimpleData.ObjectModel.Helpers;
using SimpleData.Infrastructure.Provider;

namespace SimpleData.ObjectModel.Design
{

	/// <summary>
	/// Representa uma regra do sistema, associada à um documento ou campo
	/// </summary>
	public abstract class Rule
	{
		//private IProvider<Rule, IRuleBuilder> factory = null;
		private IRuleBuilder builder = null;
		private IDataObjectSerializable<object> serializer = null;
		//private object properties;

		#region [ .ctor ]

		/// <summary>
		/// Utilizado pelo EF
		/// </summary>
		protected Rule()
		{
			this.Enabled = true;
			this.RuleData = new byte[] { };
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="name"></param>
		public Rule( RuleName name )
			: this( name, null )
		{ }

		/// <summary>
		/// 
		/// </summary>
		/// <param name="name"></param>
		/// <param name="builder"></param>
		public Rule( RuleName name, IRuleBuilder builder )
			: this()
		{
			name.Throws().IfNull();

			this.Name = name;
			this.builder = builder;
		}

		#endregion

		/// <summary>
		/// Obtém o ID que representa a Rule no sistema
		/// </summary>
		public long RuleID
		{ get; protected set; }

		/// <summary>
		/// 
		/// </summary>
		//protected string TypeWrapper
		//{
		//    get
		//    {
		//        return Convert.ToString( ( char )this.Type );
		//    }
		//    set
		//    {
		//        if ( String.IsNullOrEmpty( value ) )
		//            throw new ArgumentNullException();
		//        this.Type = ( RuleKind )value[ 0 ];
		//    }
		//}

		/// <summary>
		/// Obtém o tipo de regra que esse objeto representa
		/// </summary>
		public RuleKind Type
		{ get; protected set; }

		/// <summary>
		/// Obtém o nome que identifica os metadados da regra
		/// </summary>
		public RuleName Name
		{ get; private set; }

		/// <summary>
		/// Obtém ou define a mensagem de erro para essa regra
		/// </summary>
		public string ErrorMessageFormat
		{ get; set; }

		/// <summary>
		/// Obtém ou define uma dica para ser exibido quando a regra falar
		/// </summary>
		public string ToolTipText
		{ get; set; }

		/// <summary>
		/// Indica se a regra está ativa
		/// </summary>
		public bool Enabled
		{ get; set; }

		/// <summary>
		/// Obtém ou define os dados que serão salvos no banco de dados
		/// </summary>
		public byte[] RuleData
		{ get; set; }

		/// <summary>
		/// 
		/// </summary>
		//[Obsolete("Não utilizar. No momento está muito confuso a sua utilizade.")]
		//public object Properties
		//{
		//    get
		//    {
		//        if ( this.serializer == null )
		//        {
		//            this.serializer = this.GetBuilder().Serializer;
		//            this.properties = this.serializer.Value;
		//        }
		//        return this.properties;
		//    }
		//}

		/// <summary>
		/// Obtém ou define o objeto que realiza a criação do construtor da regra
		/// </summary>
		//public IProvider<Rule, IRuleBuilder> Factory
		//{
		//    get
		//    {
		//        if ( this.factory == null )
		//            this.factory = Runtime.Rules;
		//        return this.factory;
		//    }
		//    set { this.factory = value; }
		//}

		/// <summary>
		/// Realiza a serialização dos dados da propriedade <see cref="Properties"/>.
		/// </summary>
		public void SerializeProperties()
		{
			if ( this.serializer != null )
			{
				this.serializer.ValueChanged();
				this.RuleData = this.serializer.SerializedValue;
			}
		}

		//#region [ Method GetBuilder ]

		/// <summary>
		/// Obtém o construtor da regra
		/// </summary>
		/// <returns></returns>
		//public IRuleBuilder GetBuilder()
		//{
		//    return this.GetBuilder( this.Factory );
		//}

		/// <summary>
		/// Obtém o construtor da regra
		/// </summary>
		/// <param name="factory"></param>
		/// <returns></returns>
		//public virtual IRuleBuilder GetBuilder( IProvider<Rule, IRuleBuilder> factory )
		//{
		//    factory.Throws().IfNull();

		//    if ( this.builder == null )
		//        this.builder = factory.Create( this );

		//    return this.builder;
		//}

		//#endregion
	}
}
